package client;

import handling.opcode.SendPacketOpcode;
import server.maps.MapleMap;
import tools.DateUtil;
import tools.Pair;
import tools.Randomizer;
import tools.data.output.MaplePacketLittleEndianWriter;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;

public class MapleForce {

    private final int ownerID;
    private final int skillID;
    private final int fromMobOID;
    private final int attackCount;
    private final MapleForceType type;
    private final byte subType;
    private final byte value;
    private final List<Integer> toMobOID;
    private final List<Pair<Integer, Byte>> forceOID = new ArrayList<>();
    private final boolean isFacingLeft;

    public MapleForce(int ownerID, int skillID, int fromMobOID, MapleForceType type, byte subType, List<Integer> toMobOID, byte value, int attackCount, MapleMap map) {
        this(ownerID, skillID, fromMobOID, type, subType, toMobOID, value, attackCount, map, false);
    }

    public MapleForce(int ownerID, int skillID, int fromMobOID, MapleForceType type, byte subType, List<Integer> toMobOID, byte value, int attackCount, MapleMap map, boolean isFacingLeft) {
        this.ownerID = ownerID;
        this.skillID = skillID;
        this.fromMobOID = fromMobOID;
        this.type = type;
        this.subType = subType;
        this.toMobOID = toMobOID;
        this.value = value;
        this.attackCount = attackCount;
        this.isFacingLeft = isFacingLeft;
        if (value >= 0) {
            initForces(map);
        }
    }

    private void initForces(MapleMap map) {
        for (int i = 0; i < attackCount; i++) {
            forceOID.add(new Pair<>(map.getSpawnedForcesOnMap(), value));
        }
    }

    public void addForce(int moboid, byte value, MapleMap map) {
        toMobOID.add(moboid);
        forceOID.add(new Pair<>(map.getSpawnedForcesOnMap(), value));
    }


    public int getOwnerID() {
        return ownerID;
    }

    public int getSkillID() {
        return skillID;
    }

    public int getFromMobOID() {
        return fromMobOID;
    }

    public MapleForceType getType() {
        return type;
    }

    public byte getSubType() {
        return subType;
    }

    public List<Integer> getToMobOID() {
        return toMobOID;
    }

    public List<Pair<Integer, Byte>> getForceOID() {
        return forceOID;
    }

    public byte getValue() {
        return value;
    }

    public int getAttackCount() {
        return attackCount;
    }

    public byte[] writePacket() {
        return writePacket(null);
    }

    public byte[] writePacket(Point point) {
        MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();

        mplew.writeShort(SendPacketOpcode.FORCEATOM_CREATE.getValue());

        mplew.writeBool(getFromMobOID() > 0);
        mplew.writeInt(getOwnerID());
        if (getFromMobOID() > 0) {
            mplew.writeInt(getFromMobOID());
        }
        mplew.writeInt(getType().ordinal());
        if (getType() != MapleForceType.恶魔精气) {
            mplew.write(getSubType());
            if (getType().isMultiMob()) {
                mplew.writeInt(getToMobOID().size());
            }
            for (Integer mobid : getToMobOID()) {
                mplew.writeInt(mobid);
            }
            mplew.writeInt(getSkillID());
        }

        for (Pair<Integer, Byte> forceid : getForceOID()) {
            mplew.write(1);
            mplew.writeInt(forceid.getLeft());
            mplew.writeInt(forceid.getRight());
            switch (getType()) {
                case 恶魔精气:
                    mplew.writeInt(Randomizer.rand(0x23, 0x31));
                    mplew.writeInt(Randomizer.rand(5, 6));
                    mplew.writeInt(Randomizer.rand(0x1E, 0x44));
                    mplew.writeInt(0);
                    break;
                case 幻影卡牌:
                    mplew.writeInt(Randomizer.rand(15, 32));
                    mplew.writeInt(Randomizer.rand(7, 10));
                    mplew.writeInt(Randomizer.rand(9, 25));
                    mplew.writeInt(0);
                    break;
                case 追击盾:
                    mplew.writeInt(Randomizer.rand(15, 32));
                    mplew.writeInt(Randomizer.rand(4, 48));
                    mplew.writeInt(Randomizer.rand(48, 80));
                    mplew.writeInt(0x3C);
                    break;
                case 追击盾_反射:
                    mplew.writeInt(Randomizer.rand(32, 48));
                    mplew.writeInt(Randomizer.rand(3, 21));
                    mplew.writeInt(Randomizer.rand(0, 255));
                    mplew.writeInt(0x3C);
                    break;
                case 尖兵火箭:
                    mplew.writeInt(Randomizer.rand(15, 20));
                    mplew.writeInt(Randomizer.rand(20, 30));
                    mplew.writeInt(Randomizer.rand(120, 150));
                    mplew.writeInt(Randomizer.rand(300, 900));
                    break;
                case 宙斯盾系统:
                    mplew.writeInt(0x23);
                    mplew.writeInt(0x05);
                    mplew.writeInt(Randomizer.rand(80, 90));
                    mplew.writeInt(Randomizer.rand(100, 500));
                    break;
                case 三彩箭矢:
                    mplew.writeInt(Randomizer.rand(0x0A, 0x0E));
                    mplew.writeInt(Randomizer.rand(8, 9));
                    mplew.writeInt(Randomizer.rand(0xD3, 0x13A));
                    mplew.writeInt(Randomizer.rand(0x1E, 0x3B));
                    break;
                case 狂风肆虐:
                    mplew.writeInt(Randomizer.rand(40, 50));
                    mplew.writeInt(Randomizer.rand(5, 9));
                    mplew.writeInt(Randomizer.rand(150, 180));
                    mplew.writeInt(Randomizer.rand(30, 40));
                    break;
                case 暴风灭世:
                    mplew.writeInt(Randomizer.rand(1, 3));
                    mplew.writeInt(Randomizer.rand(7, 12));
                    mplew.writeInt(Randomizer.rand(isFacingLeft ? 270 : 90, isFacingLeft ? 270 : 90));
                    mplew.writeInt(Randomizer.rand(58, 60));
                    break;
                case 灵狐:
                    mplew.writeInt(Randomizer.rand(0x10, 0x12));
                    mplew.writeInt(0x15);
                    mplew.writeInt(0x2E);
                    mplew.writeInt(0x276);
                    break;
                case 影子蝙蝠:
                    mplew.writeInt(Randomizer.rand(2, 32));
                    mplew.writeInt(Randomizer.rand(4, 5));
                    mplew.writeInt(Randomizer.rand(48, 80));
                    mplew.writeInt(0);
                    break;
                case 影子蝙蝠_反射:
                    mplew.writeInt(Randomizer.rand(4, 48));
                    mplew.writeInt(Randomizer.rand(3, 4));
                    mplew.writeInt(Randomizer.rand(0, 255));
                    mplew.writeInt(0);
                    break;
                case 辅助导弹:
                    mplew.writeInt(50);
                    mplew.writeInt(Randomizer.rand(11, 13));
                    mplew.writeInt(Randomizer.rand(0x1A, 0x27));
                    mplew.writeInt(500);
                    break;
                case 制裁火球:
                    mplew.writeInt(Randomizer.rand(36, 39));
                    mplew.writeInt(Randomizer.rand(5, 6));
                    mplew.writeInt(Randomizer.rand(33, 64));
                    mplew.writeInt(Randomizer.rand(512, 544));
                    break;
                case 心雷合一:
                    mplew.writeInt(Randomizer.rand(10, 50));
                    mplew.writeInt(Randomizer.rand(0, 16));
                    mplew.writeInt(Randomizer.rand(30, 50));
                    mplew.writeInt(Randomizer.rand(0, 0));
                    break;
                case 爱星能量:
                    mplew.writeInt(Randomizer.rand(36, 39));
                    mplew.writeInt(Randomizer.rand(5, 6));
                    mplew.writeInt(Randomizer.rand(33, 64));
                    mplew.writeInt(Randomizer.rand(512, 544));
                    break;
                default:
                    mplew.writeZeroBytes(16);
                    break;
            }
            if (point != null) {
                mplew.writeInt(Randomizer.rand(-600 + point.x, 600 + point.x));
                mplew.writeInt(Randomizer.rand(-300 + point.y, 50 + point.y));
            } else {
                mplew.writeInt(0);
                switch (getType()) {
                    case 幻影卡牌:
                        mplew.writeInt(Randomizer.rand(0, 10));
                        break;
                    default:
                        mplew.writeInt(0);
                        break;
                }
            }
            mplew.writeInt(DateUtil.getSpecialNowiTime());
            mplew.writeInt(0);
            switch (getType()) {
                case 幻影卡牌:
                    mplew.writeInt(Randomizer.rand(0, 10));
                    break;
                default:
                    mplew.writeInt(0);
                    break;
            }
            mplew.writeInt(0);
        }
        mplew.write(0);
        switch (getType()) {
            case 影子蝙蝠:
                if (point != null) {
                    mplew.writeInt(point.x - 120);
                    mplew.writeInt(point.y - 100);
                    mplew.writeInt(point.x + 120);
                    mplew.writeInt(point.y + 100);
                } else {
                    mplew.writeZeroBytes(16);
                }
                break;
            case 影子蝙蝠_反射:
                if (point != null) {
                    mplew.writeInt(point.x);
                    mplew.writeInt(point.y);
                } else {
                    mplew.writeZeroBytes(8);
                }
                break;
            case 心雷合一:
            case 制裁火球:
                if (point != null) {
                    mplew.writeInt(point.x - 120);
                    mplew.writeInt(point.y - 100);
                    mplew.writeInt(point.x + 120);
                    mplew.writeInt(point.y + 100);
                    mplew.writeInt(0);
                } else {
                    mplew.writeZeroBytes(20);
                }
                break;
            case 爱星能量:
                mplew.writeInt(0);
                mplew.writeInt(0);
                mplew.writeInt(0);
                mplew.writeInt(0);
                mplew.writeInt(0);
                mplew.writeInt(0);
                break;
        }

        return mplew.getPacket();
    }
}
